package com.tomtop.core.logging;

import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.tomtop.core.utils.JSONUtils;
import com.tomtop.core.utils.ListUtils;
import com.tomtop.core.utils.MapUtils;

@Configuration
public class RunTimeLog implements InitializingBean {

	private static final ThreadLocal<Long> beginTime = new ThreadLocal<Long>() {
		protected Long initialValue() {
			return System.currentTimeMillis();
		};
	};
	private final static Logger LOGGER = LoggerFactory.getLogger("laolei.time.log");

	private static Map<String, Integer> timeScale = MapUtils.<String, Integer>n().a("off", 1000).a("trace", 10)
			.a("debug", 100).a("info", 200).a("warn", 2000).a("error", 8000).to();
	private static List<Entry<String, Integer>> timeScaleList;
	private static int offtime;
	static {
		init(timeScale);
	}

	private static void init(Map<String, Integer> map) {
		timeScale = MapUtils.n(map).filter((k, v) -> v != null).to();
		Integer offtime_ = timeScale.remove("off");
		offtime = offtime_ == null ? -1 : offtime_;
		timeScaleList = ListUtils.n(timeScale.entrySet()).filter(t -> t.getValue() != null).order(t -> t.getValue())
				.to();
	}

	@ConfigurationProperties("logging.timescale")
	@Bean
	Map<String, Integer> timeScale() {
		timeScale.clear();
		return timeScale;
	}

	public static final void clear() {
		beginTime.remove();
	}

	public static final void bedin() {
		beginTime.set(System.currentTimeMillis());
	}

	private static long getRuntime() {
		long bedin = beginTime.get();
		long end = System.currentTimeMillis();
		beginTime.set(end);
		return end - bedin;
	}

	public static final void log(String f, Object... args) {
		log(getRuntime(), f, args);
	}

	public static final void log(long runtime, String f, Object... args) {
		if (runtime == 0 || f == null || offtime > runtime || timeScaleList.isEmpty()) {
			return;
		}
		Entry<String, Integer> suitmin = null;
		for (Entry<String, Integer> entry : timeScaleList) {
			if (entry.getValue() > runtime)
				break;
			suitmin = entry;
		}
		StringBuffer format = new StringBuffer("执行时间:").append(runtime).append("毫秒   ").append(f);
		output(suitmin, format.toString(), args);
	}

	private static void output(Entry<String, Integer> suitmin, String f, Object... args) {
		if (suitmin == null) {
			LOGGER.debug(f, args);
		} else {
			switch (suitmin.getKey()) {
			case "trace":
				LOGGER.trace(f, args);
				break;
			case "debug":
				LOGGER.debug(f, args);
				break;
			case "info":
				LOGGER.info(f, args);
				break;
			case "warn":
				LOGGER.warn(f, args);
				break;
			case "error":
				LOGGER.error(f, args);
				break;
			default:
				LOGGER.info(f, args);
				break;
			}
		}
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		init(timeScale());
		LOGGER.info("api调用日志输出时间参数配置信息{} 日志最少输出的时间 {}", JSONUtils.toJSONString(timeScaleList), offtime);
	}
}
